/**
 * 最大请求并发数，返回Promise
 * @param {string[]} urls 请求urls数组
 * @param {number} maxNum 最大请求数量
 * @returns {Promise<any[]>} Promise
 */
function concurRequest(urls, maxNum) {
  return new Promise(resolve => {
    // 当urls数组为0时直接结束
    if (urls.length === 0) {
      resolve([]);
      return;
    }
    const results = []; // 存储每个请求的结果
    let index = 0; // 下一个请求的下标
    let count = 0; // 请求完成的数量，包括成功和失败

    // 发出请求
    async function request() {
      // 当请求等于urls数组长度，结束不在继续发请求了
      if (index === urls.length) {
        return;
      }

      const i = index; // 记录当前发出请求的下标
      const url = urls[index];
      index++; // 每发出一个请求，下标加1

      try {
        const value = await fetch(url);
        results[i] = value;
      } catch (error) {
        results[i] = error;
      } finally {
        count++;
        // 当完成请求的数量等于urls的长度时，结束
        if (count === urls.length) {
          resolve(results);
        }
        request(); // 每个请求结束后继续发请求
      }
    }

    // 取urls的长度和与maxNum的最小値，发出请求
    const times = Math.min(maxNum, urls.length);
    for (let i = 0; i < times; i++) {
      request();
    }
  });
}
